home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 03 - 1987 / 03.10 Oct 87 / RomRef sources / RomRef Edit sources / RomRef.c (edit) next >
Encoding:
Text File  |  1987-09-21  |  20.3 KB  |  740 lines  |  [TEXT/EDIT]

  1. /*  A ROM Reference Desk Accessory  */
  2. /*          Frank Alviani           */
  3. /*           Version 1.1            */
  4. /*       8:36:39 PM  8/5/86         */
  5. /*                                  */
  6. /*  Thanks to Don Melton for making */
  7. /*  this a whole bunch easier!      */
  8.  
  9. #Options R=4 Z K
  10. #include <MacDefs.h>
  11. #include <QuickDraw.h>
  12. #include <Control.h>
  13. #include <TextEdit.h>
  14. #include <Dialog.h>
  15. #include <Menu.h>
  16. #include <Events.h>
  17. #include <Desk.h>
  18. #include <DeskAccessory.c>
  19. #include <Resource.h>
  20.  
  21. /* MODIFIED DEFINITIONS
  22.  
  23. *** IMPORTANT *** Other alternate elements of the OpParamType union structure
  24. are not defined here!!!
  25.  
  26. The CntrlParam structure also must be defined because OSIO.h is not included.
  27. However, it remains unaltered. */
  28.  
  29. #define OsType long
  30. union __OP
  31.     { 
  32.     struct
  33.         {
  34.         short menuID;
  35.         short menuItem;
  36.         } menuData;
  37.     Ptr event;
  38.     };
  39.  
  40. #define OpParamType union __OP
  41.  
  42. struct __CP
  43.     {
  44.     struct __CP *ioLink;
  45.     short ioType;
  46.     short ioTrap;
  47.     Ptr ioCmdAddr;
  48.     ProcPtr ioCompletion;
  49.     short ioResult;
  50.     char *ioNamePtr;
  51.     short ioVRefNum;
  52.     short ioRefNum;
  53.     short CSCode;
  54.     OpParamType csp;
  55.     };
  56.  
  57. #define CntrlParam struct __CP
  58.  
  59. typedef struct
  60.     {
  61.     char typeName[4];
  62.     } ResType;
  63.  
  64. typedef struct {
  65. long        scrapSize;
  66. Handle      scrapHandle;
  67. short       scrapCount;
  68. short       scrapState;
  69. char        *scrapName;
  70. } ScrapStuff, *ScrapStuffPtr;
  71.  
  72. #define NULL 0
  73. #define FALSE 0
  74. #define TRUE 1
  75. #define geneva      3
  76. #define NAMES_IN_BOX 7
  77. #define TIX ((long *) 0x16A)
  78.  
  79. #define ACCEPT 1
  80. #define ACCEPT_CONT 2
  81. #define APPEND 3
  82. #define APPEND_CONT 4
  83. #define CANCEL 5
  84. #define NBOX 7
  85. #define SBAR 8
  86.  
  87. #define FRONT_WINDOW -1
  88.  
  89. /* SETUP DA HEADER AND GLUE ROUTINES
  90. *** IMPORTANT *** Invoke this macro BEFORE declaring any global variables or
  91. defining any Mac C functions!!!
  92.  
  93. Macro parameters:
  94.     1       Name of desk accessory (enclose text in single quotes)
  95.     2       Resource ID of desk accessory (12-31 inclusive)
  96.     3       Flags
  97.     4       Delay
  98.     5       Event Mask
  99.     6       Request for global variable allocation: NeedGlobals or NoGlobals
  100. */
  101.  
  102. #asm
  103.  
  104.  DeskAccessory 'ROM Ref',12,$0400,0,$0142,NeedGlobals
  105.  
  106. #endasm
  107.  
  108. /* GLOBAL VARIABLES */
  109. short           ownedID;
  110. short           no_casting;     /* 0=typecast  1=don't typecast */
  111. short           mem_mash;       /* 1=include "mashes memory" comment */
  112. short           selection;
  113. MenuHandle      hRRMenu;
  114. DialogPtr       abtDlgPtr, mgrDlgPtr, rtnDlgPtr;
  115. long            lastClick;
  116. short           lastPick;       /* used in double-click test */
  117. short           data_refNum;    /* vol ref num for data resource file */
  118. short           old_v;          /* for arrow-scrolling in dialog */
  119. ControlHandle   rtnScrlH, namScrlH; /* scroll bar in routine window */
  120. ControlHandle   vScrlH;         /* "generic" for ModalDialog filterProc */
  121. Handle          abTblH;         /* handle to abbreviation table */
  122. TEHandle        hTE;            /* for names selection routine */
  123. Rect            textR, TERect;
  124. char            call[256];      /* sample here */
  125. ScrapStuffPtr   sInfo;
  126.  
  127. /*~Open/Close/Control~ --- Open Routine --- */
  128. short open(pb, dce)
  129. CntrlParam      *pb;
  130. DeviceControl   *dce;
  131. {
  132. GrafPtr         oldPort;
  133. short           item, type, err, def_vol;
  134. ControlHandle   ctlH;
  135. Ptr             tPtr;
  136. short           pbCall();
  137.  
  138.     ownedID = 0xC000 - (32 * (1 + dce->dCtlRefNum));
  139.     dce->dCtlMenu = ownedID;
  140.  
  141.     if (!dce->dCtlWindow)
  142.       { hRRMenu = GetMenu(ownedID);
  143.         HNoPurge(hRRMenu);
  144.  
  145.         if (!(mgrDlgPtr = (DialogPtr) NewPtr(sizeof(DialogRecord))))
  146.           return -1;
  147.         mgrDlgPtr = GetNewDialog(ownedID, mgrDlgPtr, FRONT_WINDOW);
  148.         GetDItem(mgrDlgPtr, SBAR, &type, &namScrlH, &textR);  /* scrollbar */
  149.         namScrlH = NewControl(mgrDlgPtr, &textR, "\px", FALSE, 0, 0, 0,
  150.                               scrollBarProc, 0);
  151.         
  152.         if (!(rtnDlgPtr = (DialogPtr) NewPtr(sizeof(DialogRecord))))
  153.           return -1;
  154.         rtnDlgPtr = GetNewDialog(ownedID+1, rtnDlgPtr, FRONT_WINDOW);
  155.         
  156.         GetDItem(rtnDlgPtr, SBAR, &type, &rtnScrlH, &textR);  /* scrollbar */
  157.         rtnScrlH = NewControl(rtnDlgPtr, &textR, "\px", FALSE, 0, 0, 0,
  158.                               scrollBarProc, 0);
  159.         
  160.         GetDItem(rtnDlgPtr, NBOX, &type, &ctlH, &textR);  /* get scrollBOX rect */
  161.         TERect = textR;
  162.         InsetRect(&TERect, 2, 2);
  163.  
  164.         if (!(abtDlgPtr = (DialogPtr) NewPtr(sizeof(DialogRecord))))
  165.           return -1;
  166.         abtDlgPtr = GetNewDialog(ownedID+2, abtDlgPtr, FRONT_WINDOW);
  167.  
  168.         /* open data file */ 
  169.         if ((data_refNum = OpenResFile("\pRom Reference Data")) == -1)
  170.           return -1;
  171.  
  172.         if ((abTblH = GetResource('ROMA', 1)) == NULL)   /* get abb. table */
  173.           return -1;
  174.  
  175.         no_casting = 0; mem_mash = 0;
  176.         activate();
  177.       }
  178.     return 0;
  179. }
  180.  
  181. /* --- Close --- */
  182. short close(pb, dce)
  183. CntrlParam      *pb;
  184. DeviceControl   *dce;
  185. {
  186.     deActivate();
  187.     ReleaseResource(hRRMenu);
  188.     ReleaseResource(abTblH);
  189.     DisposeDialog(mgrDlgPtr);
  190.     DisposeDialog(rtnDlgPtr);
  191.     DisposeDialog(abtDlgPtr);
  192.     dce->dCtlWindow = (WindowPtr) NULL;
  193.     CloseResFile(data_refNum);  /* close data file */
  194.     return 0;
  195. }
  196.  
  197. /* --- Control --- */
  198. short control(pb, dce)
  199. CntrlParam      *pb;
  200. DeviceControl   *dce;
  201. {
  202. EventRecord     *theEvent;
  203.  
  204.     switch (pb->CSCode)
  205.       { case accEvent:
  206.           theEvent = (EventRecord *) pb->csp.event;
  207.           if (theEvent->what ==activateEvt)
  208.               if (theEvent->modifiers & activeFlag)
  209.                 activate();
  210.           break;
  211.         case accMenu:
  212.           doMenu(pb, pb->csp.menuData.menuItem, dce);
  213.           break;
  214.     }
  215.   return 0;
  216. }
  217.  
  218. activate()
  219. {
  220.   (*hRRMenu)->menuID = ownedID;
  221.   InsertMenu(hRRMenu, 0);
  222.   DrawMenuBar();
  223. }
  224.  
  225. deActivate()
  226. {
  227.     DeleteMenu(ownedID);
  228.     DrawMenuBar();
  229. }
  230.  
  231. /*~Menu Stuff~ --- Handle Menu Invocations --- */
  232. doMenu(pb, menuItem, dce)
  233. CntrlParam      *pb;
  234. short           menuItem;
  235. DeviceControl   *dce;
  236. {
  237. short       theItem;
  238. GrafPtr     tGPtr;
  239.  
  240.     switch (menuItem)
  241.       { case 1:     /* ABOUT */
  242.           dce->dCtlFlags &= 0xFBFF; /* clear dCtlEnable */
  243.           dce->dCtlFlags ^= 0x4000; /* set dNeedLock */
  244.  
  245.           ((WindowPeek) abtDlgPtr)->windowKind = 2;   /* dialogkind */
  246.           ShowWindow(abtDlgPtr);
  247.           BringToFront(abtDlgPtr);
  248.           SetPort(abtDlgPtr);
  249.           ModalDialog(NULL, &theItem);
  250.           ((WindowPeek) abtDlgPtr)->windowKind = dce->dCtlRefNum;
  251.           HideWindow(abtDlgPtr);
  252.  
  253.           dce->dCtlFlags ^= 0x0400; /* set dCtlEnable */
  254.           dce->dCtlFlags &= 0xBFFF; /* clear dNeedLock */
  255.           break;
  256.         case 2:     /* LOOKUP CALLS */
  257.           dce->dCtlFlags &= 0xFBFF; /* clear dCtlEnable */
  258.           dce->dCtlFlags ^= 0x4000; /* set dNeedLock */
  259.  
  260.           findRtn(dce);
  261.  
  262.           dce->dCtlFlags ^= 0x0400; /* set dCtlEnable */
  263.           dce->dCtlFlags &= 0xBFFF; /* clear dNeedLock */
  264.           break;
  265.         case 3:     /* DISABLE TYPECASTING */
  266.           if (no_casting)       /* was NO, now YES */
  267.             { no_casting = 0;
  268.               CheckItem(hRRMenu, 3, FALSE);
  269.             }
  270.           else
  271.             { no_casting = 1;
  272.               CheckItem(hRRMenu, 3, TRUE);
  273.             }
  274.           break;
  275.         case 4:     /* INCLUDE 'MASHES MEMORY' COMMENT */
  276.           if (mem_mash)
  277.             { mem_mash = 0;
  278.               CheckItem(hRRMenu, 4, FALSE);
  279.             }
  280.           else
  281.             { mem_mash = 1;
  282.               CheckItem(hRRMenu, 4, TRUE);
  283.             }
  284.           break;
  285.         case 5:     /* CLOSE */
  286.           close(pb, dce);
  287.           break;
  288.       }
  289.     HiliteMenu(0);
  290. }
  291.  
  292. /*~Lookup Code~ --- Heart of the DA --- */
  293. findRtn(dce)
  294. DeviceControl   *dce;
  295. {
  296. short       the_manager, item, base_res_no, pick;
  297. long        scrap_err, call_len;
  298. short       BoxPick();
  299.  
  300.   get_mgr:
  301.     /* use "select manager" dialog */
  302.     dce->dCtlWindow = 0;
  303.     /* get titles for selected manager */
  304.     SetPort(mgrDlgPtr);
  305.     item =  BoxPick(mgrDlgPtr, namScrlH, 99, &the_manager, &base_res_no);
  306.     HideWindow(mgrDlgPtr);
  307.     if (item == CANCEL) return;
  308.       
  309.     /* get titles for selected manager */
  310.     SetPort(rtnDlgPtr);
  311.     item =  BoxPick(rtnDlgPtr, rtnScrlH, the_manager+1, &pick, &base_res_no);
  312.     if (item < CANCEL )
  313.       { expandCall(base_res_no+pick, &call_len);
  314.         if (call_len)
  315.           { if (item < APPEND )
  316.               { ZeroScrap();
  317.                 scrap_err = PutScrap((long) call_len, 'TEXT', call);
  318.               }
  319.             else
  320.               AppendScrap((long) call_len, 'TEXT', call);
  321.           }
  322.       }
  323.  
  324.     ((WindowPeek) rtnDlgPtr)->windowKind = dce->dCtlRefNum;
  325.     HideWindow(rtnDlgPtr);
  326.  
  327.     if (item == ACCEPT_CONT || item == APPEND_CONT)     /* keep it up! */
  328.       goto get_mgr;
  329. }
  330.  
  331. /* --- assumes port is properly set before entry --- */
  332. /* --- returns item_no from modal dialog box --- */
  333. short BoxPick(dPtr, scrlH, resNo, sel, base)
  334. DialogPtr       dPtr;
  335. ControlHandle   scrlH;
  336. short           resNo;
  337. short           *sel;   /* zero-based! */
  338. short           *base;
  339. {
  340. short       filter();
  341. Handle      nameListH;      /* handle to names-list resource */
  342. long        call_len, nameList_len, ticks;
  343. short       res_ct, done, item, l_no, sel_st, sel_en;
  344. Point       pt;
  345.  
  346.     if ((nameListH = GetResource('ROMN', resNo)) == NULL)
  347.       { SysBeep(60);
  348.         return CANCEL;
  349.       }
  350.     nameList_len = SizeResource(nameListH);
  351.     HLock(nameListH);
  352.     res_ct = *((short *) *nameListH);   /* ct of call resources */
  353.     *base = *((short *) *nameListH+1);  /* starting call res # is 2nd short! */
  354.  
  355.     hTE = TENew(&TERect, &TERect);
  356.     (*hTE)->txFont = geneva;
  357.     (*hTE)->crOnly = -1;        /* CR breaks only */
  358.     (*hTE)->txSize = 12;
  359.     TESetText(*nameListH+4, nameList_len-4, hTE);
  360.     TECalText(hTE);
  361.     TESetSelect((*hTE)->lineStarts[0], (*hTE)->lineStarts[1], hTE);
  362.  
  363.     ((WindowPeek) dPtr)->windowKind = 2;   /* dialogkind */
  364.     ShowWindow(dPtr);
  365.     BringToFront(dPtr);
  366.     FrameRect(&textR.top);
  367.     TEUpdate(&TERect.top, hTE);
  368.     TEActivate(hTE);
  369.     ShowControl(scrlH);
  370.     SetCtlMin(scrlH, 0);
  371.     if ((*hTE)->nLines > NAMES_IN_BOX)   /* set up scrollbar */
  372.       SetCtlMax(scrlH, (*hTE)->nLines-NAMES_IN_BOX);
  373.     else
  374.       SetCtlMax(scrlH, 0);
  375.     SetCtlValue(scrlH, 0);
  376.  
  377.     done = FALSE; selection=0;
  378.     old_v = 0;
  379.     vScrlH = scrlH;
  380.     while (!done)
  381.       { ModalDialog(filter, &item);   /* filter for keystrokes only */
  382.         switch (item)
  383.           { case ACCEPT:
  384.             case ACCEPT_CONT:
  385.             case APPEND:
  386.             case APPEND_CONT:
  387.             case CANCEL:
  388.               done = TRUE;
  389.               break;
  390.             case NBOX:
  391.               GetMouse(&pt);
  392.               ticks = *TIX;
  393.               l_no = (pt.v - textR.top) / (*hTE)->lineHeight; /* relative line# */
  394.               selection = GetCtlValue(scrlH) + l_no;
  395.               if ((lastClick + 30) > ticks)
  396.                 { item = ACCEPT;     /* double click in same item */
  397.                   done = TRUE;
  398.                   break;
  399.                 }
  400.               sel_st = (*hTE)->lineStarts[selection];
  401.               if (selection >= res_ct)
  402.                 sel_en = 32767;
  403.               else
  404.                 sel_en = (*hTE)->lineStarts[selection + 1];
  405.               TESetSelect(sel_st, sel_en, hTE);
  406.               TEActivate(hTE);
  407.               lastPick = selection;
  408.               lastClick = ticks;
  409.               break;
  410.             case SBAR:
  411.               nameScroll(dPtr);
  412.               break;
  413.           }
  414.       }
  415.     TEDispose(hTE);
  416.     HUnlock(nameListH);
  417.     ReleaseResource(nameListH);
  418.     *sel = selection;
  419.     return item;
  420. }
  421.  
  422. /* --- Append to scrap, updating scrapCount - Memory Only -- */
  423. /* assumes only 1 data type in desk scrap */
  424. AppendScrap(len, type, str)
  425. long        len;
  426. long        type;   /* 4-char string */
  427. char        *str;
  428. {
  429. long            sSize, dSize;
  430.  
  431.         sInfo = (ScrapStuffPtr)0x960;
  432.         if (sInfo->scrapState <= 0) return;     /* can't do anything */
  433.         sSize = GetHandleSize(sInfo->scrapHandle);
  434.         dSize = *((long *)(*sInfo->scrapHandle) + 1);   /* get existing len */
  435.         SetHandleSize(sInfo->scrapHandle, sSize + len); /* make room */
  436.         *((long *)(*sInfo->scrapHandle) + 1) = dSize + len;
  437.         BlockMove(str, (*sInfo->scrapHandle + 8 + dSize), len);
  438. }
  439.  
  440. /*~Scrolling~ --- Filter Events, Handle Scrolling, etc. --- */
  441. short filter(dPtr, ePtr, item)
  442. DialogPtr       dPtr;
  443. EventRecord     *ePtr;
  444. short           *item;
  445. {
  446. #asm
  447.     link        A6,#0           ;no locals
  448.     movem.l     D1-D2,-(sp)     ;save
  449.     move.l      16(A6),D0
  450.     move.l      12(A6),D1
  451.     move.l      8(A6),D2
  452.     jsr         md_filter       ;call C routine
  453.     movem.l     (SP)+,D1-D2
  454.     unlk        A6
  455.     move.l      (SP)+,A0        ;return addr
  456.     add.l       #12,sp
  457.     move.b      D0,(SP)         ;return condition
  458.     jmp         (A0)
  459. #endasm
  460. }
  461.  
  462. /* uses global "vScrlH" to access vertical scrollbar in MD window */
  463. short md_filter(dPtr, ePtr, item)
  464. DialogPtr       dPtr;
  465. EventRecord     *ePtr;
  466. short           *item;
  467. {
  468. short           part, new_v, i, j, k, dV;
  469. short           sel_st, sel_en, delta;
  470. char            ch, ch2, key;
  471. Ptr             tPtr, base;
  472. short           nameScroll();
  473.  
  474.     switch(ePtr->what)
  475.       { case mouseDown:
  476.           return FALSE;       /* handle normally */
  477.           break;
  478.         case autoKey:
  479.         case keyDown:   /* select by 1st letter, cursor keys, etc. */
  480.           ch = ePtr->message & 0xFF;
  481.           if (ch==0x03 || ch==0x0D)     /* enter or return */
  482.             { *item = 1;    /* accept */
  483.               return TRUE;
  484.             }
  485.           /* check for up/down arrow keys */
  486.           if (old_v <= GetCtlMax(vScrlH))   /* don't update if in last paneful */
  487.             old_v = GetCtlValue(vScrlH);
  488.           j = GetCtlMax(vScrlH);
  489.           TEDeactivate(hTE);
  490.           TESetSelect(0, 0, hTE);
  491.           key = (ePtr->message & 0xFF00) >> 8;
  492.           if (key == 0x4D) /* up arrow on Mac+ */
  493.             { i = old_v-1;
  494.               if (i < 0) i = 0;
  495.               goto qa1;
  496.             }
  497.           if (key == 0x48) /* down arrow on Mac+ */
  498.             { i = old_v + 1;
  499.               goto qa1;
  500.             }
  501.           /* look up 1st entry starting with given key or higher */
  502.           ch &= (~0x20);   /* force uppercase */
  503.           HLock((*hTE)->hText);     /* lock text for examination */
  504.           base = *(*hTE)->hText;
  505.           for (i=0;i<j;i++)
  506.             { tPtr = base + (*hTE)->lineStarts[i];
  507.               ch2 = *tPtr & (~0x20);    /* 1st char of line, upper-cased */
  508.               if (ch2 >= ch)            /* found desired line */
  509.                 break;
  510.             }
  511.           HUnlock((*hTE)->hText);
  512.         qa1:
  513.           if (i <= j)   /* in normal range, scroll */
  514.             { dV = (old_v - i) * (*hTE)->lineHeight;
  515.               SetCtlValue(vScrlH, i);
  516.               TEScroll(0, dV, hTE);
  517.             }
  518.           
  519.           if (i >= GetCtlMax(vScrlH)+NAMES_IN_BOX)
  520.             { i = GetCtlMax(vScrlH)+NAMES_IN_BOX-1;   /* can't go too far */
  521.               sel_en = 32767;
  522.               k = (*hTE)->nLines-1;
  523.               sel_st = (*hTE)->lineStarts[k];
  524.             }
  525.           else
  526.             { sel_en = (*hTE)->lineStarts[i+1];
  527.               sel_st = (*hTE)->lineStarts[i];
  528.             }
  529.           TESetSelect(sel_st, sel_en, hTE);
  530.           old_v = i;
  531.           selection = i;    /* in global so ACCEPT works */
  532.           TEActivate(hTE);
  533.           return TRUE;
  534.           break;
  535.         default:
  536.           return FALSE;
  537.           break;
  538.       }
  539. }
  540.  
  541. void nameScroll(dPtr)
  542. DialogPtr   dPtr;
  543. {
  544. short           part, new_part, old_v, new_v, dV;
  545. ControlHandle   ctlH;
  546. Point           pt;
  547. void            scroll_up(), scroll_dn();
  548.  
  549.     GetMouse(&pt);
  550.     if (part = FindControl(&pt, dPtr, &ctlH))
  551.       { old_v = GetCtlValue(ctlH);
  552.         switch (part)
  553.           { case inThumb:
  554.               new_part = TrackControl(ctlH, &pt, NULL);
  555.               if (new_part == part)     /* redraw box */
  556.                 { TEDeactivate(hTE);
  557.                   new_v = GetCtlValue(ctlH);
  558.                   dV = (old_v - new_v) * (*hTE)->lineHeight;
  559.                   TEScroll(0, dV, hTE);
  560.                 }
  561.               break;
  562.             case inUpButton:
  563.               TrackControl(ctlH, &pt, scroll_up);
  564.               break;
  565.             case inDownButton:
  566.               TrackControl(ctlH, &pt, scroll_dn);
  567.               break;
  568.             case inPageUp:
  569.               new_v = old_v - (NAMES_IN_BOX-1);
  570.               if (old_v-new_v < 0)
  571.                 { dV = old_v * (*hTE)->lineHeight;    /* stop at beginning */
  572.                   SetCtlValue(ctlH, 0);
  573.                 }
  574.               else
  575.                 { dV = (NAMES_IN_BOX-1) * (*hTE)->lineHeight;
  576.                   SetCtlValue(ctlH, new_v);
  577.                 }
  578.               TEScroll(0, dV, hTE);
  579.               break;
  580.             case inPageDown:
  581.               new_v = old_v + (NAMES_IN_BOX-1);
  582.               if (new_v > GetCtlMax(ctlH))
  583.                 { dV = -(GetCtlMax(ctlH) - old_v) * (*hTE)->lineHeight;
  584.                   SetCtlValue(ctlH, GetCtlMax(ctlH));
  585.                 }
  586.               else
  587.                 { dV = -(NAMES_IN_BOX-1) * (*hTE)->lineHeight;
  588.                   SetCtlValue(ctlH, new_v);
  589.                 }
  590.               TEScroll(0, dV, hTE);
  591.               break;
  592.           }
  593.         selection = new_v = GetCtlValue(ctlH);
  594.         TESetSelect((*hTE)->lineStarts[new_v], (*hTE)->lineStarts[new_v+1], hTE);
  595.         TEActivate(hTE);
  596.       }
  597. }
  598.  
  599. void my_scroll_up(theControl, part)
  600. ControlHandle   theControl;
  601. short           part;
  602. {
  603. short   v;
  604.  
  605.     if (part == inUpButton)   /* */
  606.       { v = GetCtlValue(theControl);
  607.         if (v == 0) return;
  608.         SetCtlValue(theControl, v-1);
  609.         TEScroll(0, (*hTE)->lineHeight, hTE);
  610.       }
  611.     return;
  612. #asm
  613. scroll_up:
  614.     MOVE.L  (SP)+,A0        ;RETURN
  615.     MOVE.W  (SP)+,D1        ;PART
  616.     MOVE.L  (SP)+,D0        ;CTL HANDLE
  617.     MOVE.L  A0,-(SP)
  618.     MOVEM.L A3-A4/D3-D7,-(SP)
  619.     JSR     my_scroll_up
  620.     MOVEM.L (SP)+,A3-A4/D3-D7
  621.     RTS
  622. #endasm
  623. }
  624.  
  625. void my_scroll_dn(theControl, part)
  626. ControlHandle   theControl;
  627. short           part;
  628. {
  629. short   v;
  630.  
  631.     if (part == inDownButton)
  632.       { v = GetCtlValue(theControl);
  633.         if (v == GetCtlMax(theControl)) return;
  634.         SetCtlValue(theControl, v+1);
  635.         TEScroll(0, -(*hTE)->lineHeight, hTE);
  636.       }
  637.     return;
  638. #asm
  639. scroll_dn:
  640.     MOVE.L  (SP)+,A0        ;RETURN
  641.     MOVE.W  (SP)+,D1        ;PART
  642.     MOVE.L  (SP)+,D0        ;CTL HANDLE
  643.     MOVE.L  A0,-(SP)
  644.     MOVEM.L A3-A4/D3-D7,-(SP)
  645.     JSR     my_scroll_dn
  646.     MOVEM.L (SP)+,A3-A4/D3-D7
  647.     RTS
  648. #endasm
  649. }
  650.  
  651. /*~Prototype Expansion~ --- Resource -> usable call --- */
  652. void expandCall(res_no, len)
  653. short       res_no;
  654. long        *len;
  655. {
  656. Handle      rHndl;
  657. short       i, j, isVar;
  658. long        rSize;
  659. unsigned char   *rPtr, ch, abb[32];
  660.  
  661.     if ((rHndl = GetResource('ROMC', res_no)) == NULL)
  662.       { SysBeep(30);
  663.          *len = 0; *call = NULL;
  664.          return;
  665.       }
  666.     rSize = SizeResource(rHndl);
  667.     HLock(rHndl);
  668.     rPtr = (unsigned char *) *rHndl;
  669.     HLock(abTblH);      /* lock abb. table */
  670.  
  671.     /* deal with "memory mashing" */
  672.     j=0;
  673.     if (mem_mash) 
  674.       { if (*(rPtr++))   /* this one moves memory */
  675.           appStr("/* mashes memory */ ", call, &j)
  676.       }
  677.     else
  678.       rPtr += 1;    /* just skip flag */
  679.  
  680.     for (i=1;i<rSize;i++)    /* copy into output, expanding abbreviations */
  681.       { if (*rPtr < 0x80)   /* normal char */
  682.           { call[j++] = *(rPtr++);
  683.             continue;
  684.           }
  685.         if (no_casting == NULL)
  686.           { if (*rPtr >= 0xC0)   /* "var" */
  687.               { isVar = 1; ch = *rPtr - 0x40;
  688.               }
  689.             else
  690.               { isVar = 0; ch = *rPtr;
  691.               }
  692.             call[j++] = '(';
  693.             findabb(ch, abb);     /* lookup typecast */
  694.             appStr(abb, &(call[j]), &j);
  695.             if (isVar)
  696.               { call[j++] = ' '; call[j++] = '*';
  697.               }
  698.             call[j++] = ')';
  699.           }
  700.         rPtr += 1;
  701.       }
  702.  
  703.     appStr(";\n", &(call[j]), &j);
  704.     *len = j;
  705.     HUnlock(rHndl);
  706.     HUnlock(abTblH);
  707.     ReleaseResource(rHndl);
  708. }
  709.  
  710. void appStr(src, target, tLen)
  711. char    *src;       /* string copied FROM, null-terminated */
  712. char    *target;    /* string appended TO */
  713. short   *tLen;      /* initial length of target; updated */
  714. {
  715. long    ct=0;
  716. Ptr     tp;
  717.  
  718.     tp = src;
  719.     while (*(tp++))
  720.       ct++;
  721.     BlockMove(src, target, ct);
  722.     *tLen = *tLen + ct;
  723. }
  724.  
  725. void findabb(c, dest)
  726. unsigned char   c;
  727. unsigned char   *dest;
  728. {
  729. short   i,j;
  730. Ptr     tPtr;
  731.  
  732.     tPtr = *abTblH;
  733.     j = c - 0x80;
  734.     for (i=0;i<j;i++)
  735.       while (*(tPtr++));
  736.     while (*tPtr)
  737.       *(dest++) = *(tPtr++);
  738.     *dest = NULL;
  739. }
  740.